// 文件名：string_view_header_fields.cpp
// 目的：从原始 HTTP 头部文本中解析出“字段名 -> 字段值”的映射，尽量避免拷贝。
// 设计说明：
//   - 入参为 std::string_view headers：仅为视图，不拥有数据；
//   - 返回 unordered_map<string, string_view>：
//       * key 使用 std::string（拷贝字段名），便于作为哈希表键长期保有；
//       * value 使用 string_view，直接指向原始 headers 中对应的子串，避免复制（高效）。
//   - 逐行处理，行分隔符为 "\r\n"；遇到空行（行长度为 0）则认为头部结束；
//   - 每行用 ':' 分隔“字段名: 值”，若冒号后存在空格则跳过前导空格（按常见格式处理）。
// 复杂度：O(N)，N 为头部总字节数（find/substring 按次线性）。
// 注意事项（重要）：
//   - 生命周期：返回的 string_view 必须不超过传入的 headers 所指向缓冲区的生命周期；
//     本示例中在 main 中传入的是 std::string rawHeaders，且 rawHeaders 在使用期间仍有效，因此安全。
//   - 重名字段：HTTP 中可能出现重复字段（如 Set-Cookie、Accept）；此处使用 emplace，若 key 已存在则忽略后续同名字段；
//     若需支持多值，可改为 unordered_multimap<string, string_view> 或 map<string, vector<string_view>>。
//   - 解析健壮性：示例未进行大小写归一或折叠多行头（header folding）；生产代码需遵循 RFC 更严格处理。

#include <iostream>
#include <string>
#include <string_view>
#include <unordered_map>

std::unordered_map<std::string, std::string_view>
parseHeaders(std::string_view headers) {
    std::unordered_map<std::string, std::string_view> result;

    while (!headers.empty()) {
        std::size_t lineEnd = headers.find("\r\n");
        std::string_view line = headers.substr(0, lineEnd);
        if (line.empty()) {
            break; // 遇到空行，头部结束
        }

        std::size_t colon = line.find(':');
        if (colon != std::string_view::npos) {
            std::string key(line.substr(0, colon)); // 转换为 string 作为 map key
            std::string_view value = line.substr(colon + 1);
            // 去除冒号后的前导空格
            while (!value.empty() && value.front() == ' ') {
                value.remove_prefix(1);
            }
            result.emplace(std::move(key), value);
        }

        if (lineEnd == std::string_view::npos) {
            break;
        }
        headers.remove_prefix(lineEnd + 2); // 跳过 "\r\n"
    }
    return result;
}

int main() {
    std::string rawHeaders =
        "Content-Type: application/json\r\n"
        "Content-Length: 42\r\n"
        "Connection: keep-alive\r\n"
        "\r\n";

    auto headerViews = parseHeaders(rawHeaders);
    std::cout << "Content-Type: " << headerViews["Content-Type"] << '\n';
    std::cout << "Content-Length: " << headerViews["Content-Length"] << '\n';
    return 0;
}